package de.slothsoft.commons.swing;

import javax.swing.text.AbstractDocument;
import javax.swing.text.BoxView;
import javax.swing.text.ComponentView;
import javax.swing.text.Element;
import javax.swing.text.IconView;
import javax.swing.text.LabelView;
import javax.swing.text.MutableAttributeSet;
import javax.swing.text.ParagraphView;
import javax.swing.text.StyleConstants;
import javax.swing.text.TabSet;
import javax.swing.text.View;
import javax.swing.text.ViewFactory;
import javax.swing.text.rtf.RTFEditorKit;

public class CodeEditorKit extends RTFEditorKit {

    private static final long serialVersionUID = 1L;

    private ViewFactory defaultFactory = new CodeViewFactory();

    @Override
    public ViewFactory getViewFactory() {
	return this.defaultFactory;
    }

    @Override
    public MutableAttributeSet getInputAttributes() {
	MutableAttributeSet result = super.getInputAttributes();
	result.removeAttribute("line_break_attribute"); //$NON-NLS-1$
	return result;
    }

    /*
	 * 
	 */

    public static class CodeViewFactory implements ViewFactory {

	@Override
	public View create(Element element) {
	    String kind = element.getName();
	    if (kind != null) {
		if (kind.equals(AbstractDocument.ContentElementName))
		    return new LabelView(element);
		else if (kind.equals(AbstractDocument.ParagraphElementName))
		    return new CodeParagraphView(element);
		else if (kind.equals(AbstractDocument.SectionElementName))
		    return new BoxView(element, View.Y_AXIS);
		else if (kind.equals(StyleConstants.ComponentElementName))
		    return new ComponentView(element);
		else if (kind.equals(StyleConstants.IconElementName))
		    return new IconView(element);
	    }

	    // default to text display
	    return new LabelView(element);
	}
    }

    public static class CodeParagraphView extends ParagraphView {

	public static final int TAB_SIZE = 10;

	public CodeParagraphView(Element elem) {
	    super(elem);
	}

	@Override
	public void layout(int width, int height) {
	    // this is for no wrapping
	    super.layout(Short.MAX_VALUE, height);
	}

	@Override
	public float getMinimumSpan(int axis) {
	    return super.getPreferredSpan(axis);
	}

	@Override
	public float nextTabStop(float x, int tabOffset) {
	    TabSet tabs = getTabSet();
	    if (tabs == null)
		// a tab every 72 pixels.
		return getTabBase() + ((int) x / TAB_SIZE + 1) * TAB_SIZE;
	    return super.nextTabStop(x, tabOffset);
	}
    }
}
